Runloop黑魔法之复活APP

Runloop黑魔法之复活APP

看到这个标题是不是觉得很酷炫,但是我还要是解释一下标题是什么意思,以免有人说我标题党,我现在要做的就是当APP发生Crash的时候,不要让APP闪退,而是重新复活。

换句话可以这么形容,把一个Crash信息吞掉,大家当没事发生过。

说得这么牛批,这个东西有什么实际的用处呢?额,其实还真的没啥实际的用处,不过我们当发生异常信息的时候可以友好的弹一个框告诉用户当前发生了异常,是选择上传异常信息继续运行还是直接退出,当然继续运行依然会有Crash风险。

接下来我们就来实现这么一个事情吧。

原理

大家都知道,我们的APP能随时的处理事件就是因为有Runloop的存在,Runloop顾名思义就是一个环,不断的跑,并且Runloop是事件驱动的,也就是说没有事情做得时候就休眠,当有事情做的时候就做事情。

Runloop实际上是一个对象,这个对象管理了其所需要的消息和事件,并且提供了一个入口函数。线程执行了该函数之后,就会一直处于Runloop的内部,而Runloop的内部就会一直处于接受消息->处理->等待->接受消息这样的循环中。直到这个循环结束,线程才会退出。

想想如果我们的APP接受到Exception消息的时候,我们先获得当前的Runloop,然后获取所有的mode,自行创建一个死循环,让runloop在里面执行不同的mode,这样就相当于让Runloop起死回生了,这样APP也复活了。

如何实现

在我前面写得这一篇iOSCrash信息上报和处理中我们已经实现了监听Exception事件,所以我们在监听到该事件之后插入以下代码即可:

1
2
3
4
5
6
7
8
//获得当前的runloop并且重新启动
CFRunLoopRef runloop = CFRunLoopGetCurrent();
NSArray *modes = CFBridgingRelease(CFRunLoopCopyAllModes(runloop));
while (!self.isExit) {
for (NSString *mode in modes) {
CFRunLoopRunInMode((CFStringRef)mode, 0.001, false);
}
}

我们来逐行看一下上面的代码,首先我们获取到当前的Runloop,然后我们获取到当前Runloop的所有mode,然后我们创建一个循环,在里面不断的跑所有的mode,这样就实现了APP的复活。

这里是完整的demo

总结

Runloop是个好东西,它能做的事情远远超出我们的想像,虽然我们开发中很少直接去接触Runloop,但是它却起着无比重要的作用,所以下面提供一些关于Runloop的资料介绍:

sunnyxx线下分享Runloop
ibireme深入理解Runloop

-------评论系统采用disqus,如果看不到需要翻墙-------------